package com.sunrise.gateway.commons.watermark;

import com.alibaba.simpleimage.render.ReadRender;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifDirectoryBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

/**
 * Created by wangmin on 2017/7/5.
 */
public abstract class WatermarkUtils {
    private final static Logger logger = LoggerFactory.getLogger(WatermarkUtils.class);


    // 获取图片的旋转角度
    public static int getImageRotateAngle(InputStream inputStream) throws Exception {
        int angle = 0;
        Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
        ExifDirectoryBase directory = metadata.getFirstDirectoryOfType(ExifDirectoryBase.class);
        if (null != directory && directory.containsTag(ExifDirectoryBase.TAG_ORIENTATION)) {
            // Exif信息中方向　　
            int orientation = directory.getInt(ExifDirectoryBase.TAG_ORIENTATION);

            // 原图片的方向信息
            if (6 == orientation) {
                angle = 90;
            } else if (3 == orientation) {
                angle = 180;
            } else if (8 == orientation) {
                angle = 270;
            }
        }

        return angle;
    }
    // 计算旋转之后的大小
    public static Rectangle calcRotatedSize(Rectangle src, int angle) {
        // if angel is greater than 90 degree, we need to do some conversion
        if (angle >= 90) {
            if (angle / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angle = angle % 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angle) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angle)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }

    public static class MyImageInfo {
        public BufferedImage bufferedImage;
        public int width;
        public int height;

        public MyImageInfo(BufferedImage bufferedImage, int width, int height) {
            this.bufferedImage = bufferedImage;
            this.width = width;
            this.height = height;
        }
    }

    // 读取并根据图片的旋转信息旋转图片
    public static MyImageInfo readAndRotateImage(InputStream inputStream) throws Exception {
        try {
            int angle = getImageRotateAngle(inputStream);

            inputStream.reset();
            ReadRender readRender = new ReadRender(inputStream);
            BufferedImage srcBufferedImage = readRender.render().getAsBufferedImage();

            if (0 == angle) {
                int width = srcBufferedImage.getWidth();
                int height = srcBufferedImage.getHeight();
                return new MyImageInfo(srcBufferedImage, width, height);
            }

            int srcWidth = srcBufferedImage.getWidth();
            int srcHeight = srcBufferedImage.getHeight();

            Rectangle destRect = calcRotatedSize(new Rectangle(new Dimension(srcWidth, srcHeight)), angle);

            BufferedImage resBufferedImage = new BufferedImage(destRect.width, destRect.height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = resBufferedImage.createGraphics();

            g2.translate((destRect.width - srcWidth) / 2, (destRect.height - srcHeight) / 2);
            g2.rotate(Math.toRadians(angle), srcWidth / 2, srcHeight / 2);

            g2.drawImage(srcBufferedImage, null, null);

            return new MyImageInfo(resBufferedImage, destRect.width, destRect.height);
        } finally {
            try {
                inputStream.close();
            } catch (Exception e) {
                logger.info("", e);
            }
        }
    }


    public static String RESULT_IMAGE_TYPE = "JPEG";


    // 将输入流转化为可以加水印的流
    public static InputStream convertToMarkSupported(InputStream inputStream) throws IOException {
        if (!inputStream.markSupported()) {
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);

            inputStream.close();

            return new ByteArrayInputStream(bytes);
        } else {
            return inputStream;
        }
    }




    /**
     * 在右下角打印文字水印
     *
     * @param inputStream  输入流
     * @param outputStream 输出流
     * @return 文件后缀
     */
    private static String printWatermarkTextRightBottom(InputStream inputStream, OutputStream outputStream, java.util.List<WatermarkParam> watermarkParamList) throws Exception {
        inputStream = convertToMarkSupported(inputStream);

        MyImageInfo myImageInfo = readAndRotateImage(inputStream);

        Graphics2D g2 = myImageInfo.bufferedImage.createGraphics();
        watermarkParamList = WatermarkTextPositionUtils.computeTextPosition(myImageInfo, g2, watermarkParamList);

        for (WatermarkParam param : watermarkParamList) {
            g2.setFont(new Font(param.fontName, param.fontStyle, param.fontSize));
            g2.setColor(param.color);
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, param.alpha));
            g2.drawString(param.text, param.printX, param.printY);
        }

        g2.dispose();

        ImageIO.write(myImageInfo.bufferedImage, RESULT_IMAGE_TYPE, outputStream);
        return RESULT_IMAGE_TYPE;
    }


    public static WatermarkResult parseAndPrintWatermark(InputStream inputStream, String watermarkParamsStr) throws Exception {
        java.util.List<WatermarkParam> watermarkParamList = WatermarkParamUtils.parseWatermarkParams(watermarkParamsStr);
        if (null == watermarkParamList || watermarkParamList.isEmpty())
            return null;

        org.apache.commons.io.output.ByteArrayOutputStream baos = new org.apache.commons.io.output.ByteArrayOutputStream();
        String imageFormat = WatermarkUtils.printWatermarkTextRightBottom(inputStream, baos, watermarkParamList);
        if (null == imageFormat)
            return null;
        else
            return new WatermarkResult(baos.toByteArray(), imageFormat);
    }


    public static void main(String[] argv) throws Exception {
        File inputFile = new File("C:\\Users\\Administrator\\Desktop\\1.jpg");
        FileInputStream fis = new FileInputStream(inputFile);

        java.util.List<WatermarkParam> watermarkParamList = new ArrayList<>();
        watermarkParamList.add(new WatermarkParam("我们222222222222222222222222222", "方正黑体", Font.PLAIN, 25, Color.RED, 10, 30, 1.0F));
        watermarkParamList.add(new WatermarkParam("我们啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊", "方正黑体", Font.PLAIN, 25, Color.RED, 10, 0, 1.0F));


        File outputFile = new File("C:\\Users\\Administrator\\Desktop\\2.jpg");
        FileOutputStream fos = new FileOutputStream(outputFile);

        String format = printWatermarkTextRightBottom(fis, fos, watermarkParamList);
        System.out.println("format = " + format);
    }
}
